`timescale 1ns / 1ps

`define SLICE(BIT, IDX) (``BIT``) * (``IDX``) + (``BIT``) - 1 : (``BIT``) * (``IDX``)

// Without delay line
// Latency = 2 + N_PE
// N_PE >= 1
module pwc2_pechain
#(
    parameter N_PE      = 4,
    parameter BIT_I     = 8,
    parameter BIT_W     = 5,
    parameter BIT_O     = 16
)
(
    input   clk,
    input   ce,
    input   ce_acc,
    input   ld_acc,
    
    input   [N_PE*BIT_I-1 : 0]     i_data,
    input   [N_PE*BIT_W-1 : 0]     i_wigt,
    
    output  [BIT_O-1 : 0]          o_data
);

wire [BIT_O-1 : 0] chain [N_PE-1 : 0];

assign chain[0] = { BIT_O{1'b0} };

pwc_pe_tail #(
    .BIT_I ( BIT_I  ),
    .BIT_W ( BIT_W  ),
    .BIT_O ( BIT_O  )
) inst_tailer (
    .clk                     ( clk      ),

    .ce                      ( ce       ),
    .ce_acc                  ( ce_acc   ),
    .ld_acc                  ( ld_acc   ),

    .i_data                  ( i_data[ `SLICE(BIT_I, N_PE - 1) ] ),
    .i_wigt                  ( i_wigt[ `SLICE(BIT_W, N_PE - 1) ] ),
    .i_prev                  (  chain[N_PE - 1] ),

    .o_data                  ( o_data           )
);

genvar i;
generate
    // pe chain
    for (i = 0; i < N_PE - 1; i = i + 1)
    begin
        pwc_pe_body #(
            .BIT_I ( BIT_I  ),
            .BIT_W ( BIT_W  ),
            .BIT_O ( BIT_O  )
        ) inst_body (
            .clk                     ( clk      ),
            .ce                      ( ce       ),

            .i_data                  ( i_data[ `SLICE(BIT_I, i) ] ),
            .i_wigt                  ( i_wigt[ `SLICE(BIT_W, i) ] ),
            .i_prev                  ( chain[i]     ),
            // .i_prev                  ( 16'b0     ),

            .o_next                  ( chain[i + 1] )
        );
    end
endgenerate

endmodule

